/*******************************************************************************
 ** 
 ** (C) 2011 Kevin Druelle 
 **
 ** this software is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 ** 
 ** This software is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 ** 
 ** You should have received a copy of the GNU General Public License
 ** along with this software.  If not, see <http://www.gnu.org/licenses/>.
 ** 
 ******************************************************************************/


#include <cpptoolbox/string.h>

#include <locale>
#include <sstream>
#include <algorithm>

std::string cpptoolbox::toUpper(const std::string & str) {
    std::string::const_iterator it = str.begin();
    std::string s_;
    while (it != str.end()) {
        s_.append(1, std::use_facet
                <std::ctype<std::string::value_type> >(std::locale()).toupper(*it));
        ++it;
    }
    return s_;
}

std::string cpptoolbox::toLower(const std::string & str) {
    std::string::const_iterator it = str.begin();
    std::string s_;
    while (it != str.end()) {
        s_.append(1, std::use_facet
                <std::ctype<std::string::value_type> >(std::locale()).tolower(*it));
        ++it;
    }
    return s_;
}


std::vector<std::string> cpptoolbox::split(const std::string & str, char delim){
    std::vector<std::string> elems;
    std::stringstream ss(str);
    std::string item;
    while(std::getline(ss, item, delim)){
        elems.push_back(item);
    }
    return elems;
}

std::string cpptoolbox::pad(const std::string& str, size_t width, char pad, alignment_t align){
    std::string padded = str;
    size_t char_to_pad = 0;
    
    if(width > str.size()){
        char_to_pad = width - str.size();
    }
    
    switch(align){
        case align_left:
            padded.insert(padded.end(), char_to_pad, pad);
            break;
        case align_right:
            padded.insert(padded.begin(), char_to_pad, pad);
            break;
        case align_center:
            padded.insert(padded.begin(), (char_to_pad % 2) == 0 ? char_to_pad / 2 : (char_to_pad / 2) + 1, pad);
            padded.insert(padded.end(), (char_to_pad % 2) == 0 ? char_to_pad / 2 : (char_to_pad / 2) + 1, pad);
            break;
    }
    return padded;
}

struct trimer_st{
    std::string pattern;
    bool operator()(char c){
        return pattern.find(c) != std::string::npos;
    }
};

std::string cpptoolbox::trim_left(const std::string& str, const std::string& trim){
    std::string trimed = str;
    struct trimer_st trimer;
    trimer.pattern = trim;
    while (!trimed.empty() && trimer(trimed.at(0))) {
        trimed.erase(0, 1);
    }
    return trimed;
}

std::string cpptoolbox::trim_right(const std::string& str, const std::string& trim){
    std::string trimed = str;
    struct trimer_st trimer;
    trimer.pattern = trim;
    while (!trimed.empty() && trimer(trimed.at(trimed.size() - 1))) {
        trimed.erase(trimed.end() - 1);
    }
    return trimed;
}

std::string cpptoolbox::trim(const std::string& str, const std::string& trim){
    std::string trimed = str;
    struct trimer_st trimer;
    trimer.pattern = trim;
    trimed.erase(std::remove_if(trimed.begin(), trimed.end(), trimer), trimed.end());
    return trimed;
}

// int cppfac::compareToIgnoreCase(const std::string & str1, const std::string & str2){
//	std::string fstr1, fstr2;
//	fstr1 = toLower(str1);
//	fstr2 = toLower(str2);
//	return strcmp(fstr1.c_str(), fstr2.c_str());
// }
//
// 
// std::vector<std::string> split(const std::string & str, const std::string & delim){
//     std::vector<std::string> elems;
//     std::stringstream ss(str);
//     std::string item;
//      while(std::getline(ss, item, delim[0])) {
//        elems.push_back(item);
//    }
//    return elems;
// }